﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;

using Storm;
using Storm.Docking;
using Storm.Docking.Controls;
using Storm.Docking.Controls.Float;
using Storm.Docking.Visual;
using Storm.Docking.Visual.Drawing;
using Storm.Docking.Visual.Glyphs;

namespace Storm.Docking.Visual
{
    /// <summary>
    /// Represents a caption bar in the top of a docked
    /// DockPanel.
    /// </summary>
	[ToolboxItem(false)]
    public class DockCaption
        : Panel
    {
        #region Fields

        private DockPanel dockPanel = null;
        private DockPane  dockPane  = null;

        private bool   focused     = false;
        private string captionText = "Caption";

		private Point lastPos = new Point(0, 0);
		private DockRenderer renderer = null;

        // Glyphs.
        private CloseGlyph   closeGlyph   = null;
        private OptionsGlyph optionsGlyph = null;

        #region Events

        /// <summary>
        /// Occurs when the DockCaption recieves focus.
        /// </summary>
        public event EventHandler RecieveFocus;

        /// <summary>
        /// Occurs when the DockCaption loses focus.
        /// </summary>
        public event EventHandler ReleaseFocus;

        #endregion

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the parent DockPanel.
        /// </summary>
        [Browsable(true)]
        [Description("Gets or sets the parent DockPanel.")]
        public DockPanel DockPanel
        {
            get { return dockPanel; }
            set
            {
                dockPanel = value;

                // Update the DockPanel/DockPane fields of the
                // DockCaption to make sure the DockCaption is
                // where it should be.

                dockPanel.Controls.Add(this);
                this.Parent = dockPanel;

				if (dockPanel.DockPane != null)
				{
					dockPane = dockPanel.DockPane;
					this.Font = this.DockPane.Renderer.DockColorTable.PaneFont;
				}
            }
        }

        /// <summary>
        /// Gets the parent DockPane.
        /// </summary>
        [Browsable(false)]
        [Description("Gets the parent DockPane.")]
        public DockPane DockPane
        {
            get { return dockPane; }
        }

        /// <summary>
        /// Gets whether the DockCaption currently has focus.
        /// </summary>
        [Browsable(false)]
        [Description("Gets whether the DockCaption currently has focus.")]
        public new bool Focused
        {
            get { return focused; }
        }

        /// <summary>
        /// Gets or sets the text of the DockCaption.
        /// </summary>
        [Browsable(true)]
        [Description("Gets or sets the text of the DockCaption.")]
        public string CaptionText
        {
            get { return captionText; }
            set
            {
                captionText = value;
                this.Invalidate();  // Redraw to show the changes.
            }
        }

        /// <summary>
        /// Gets or sets the text of the DockCaption.
        /// </summary>
        [Browsable(true)]
        [Description("Gets or sets the text of the DockCaption.")]
        public new string Text
        {
            get { return this.CaptionText; }
            set { this.CaptionText = value; }
        }

        /// <summary>
        /// Gets the CloseGlyph of the DockCaption.
        /// </summary>
        [Browsable(false)]
        [Description("Gets the CloseGlyph of the DockCaption.")]
        public CloseGlyph CloseGlyph
        {
            get { return closeGlyph; }
        }

        /// <summary>
        /// Gets the OptionsGlyph of the DockCaption.
        /// </summary>
        [Browsable(false)]
        [Description("Gets the CloseGlyph of the DockCaption.")]
        public OptionsGlyph OptionsGlyph
        {
            get { return optionsGlyph; }
        }

		/// <summary>
		/// Gets or sets the DockRenderer of the DockCaption.
		/// </summary>
		[Browsable(false)]
		[Description("Gets or sets the DockRenderer of the DockCaption.")]
		public DockRenderer Renderer
		{
			get { return renderer; }
			set
			{
				renderer = value;

				optionsGlyph.OnParentRecieveFocus(this, EventArgs.Empty);
				closeGlyph.OnParentRecieveFocus(this, EventArgs.Empty);

				optionsGlyph.Invalidate();
				closeGlyph.Invalidate();

				this.Invalidate();
			}
		}

        #endregion

        #region Methods

        #region Protected

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
		/// </summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
			this.Renderer.CaptionDrawBar(this, e.Graphics);
            base.OnPaint(e);
        }

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
		/// </summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
		protected override void OnMouseUp(MouseEventArgs e)
		{
			this.DockPanel.DockPane.HideDockRectangles();

			if (e.Button == MouseButtons.Left && this.FindForm() is DockForm)
				this.DockPanel.MakeDocked();

			base.OnMouseUp(e);
		}

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
		/// </summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left)
			{
				DockPanel dockPanel = this.DockPanel;

				if (dockPanel.DockPanelState == DockPanelState.Docked && this.FindForm() is DockForm == false)
				{
					dockPanel.MakeFloating();
					dockPanel.DockForm.Location = Cursor.Position;
				}

				this.DockPanel.DockPane.ShowDockRectangles();
			}

			base.OnMouseDown(e);
		}

		/// <summary>
		/// Raises the <see cref="E:System.Windows.Forms.Control.MouseMove"/> event.
		/// </summary>
		/// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (e.Button == MouseButtons.Left && lastPos != e.Location)
			{
				// If the DockPanel is floating, we want to move
				// it around like we would with a normal Form.

				Form form = this.FindForm();
				if (form is DockForm)
				{
					DockForm dockForm = form as DockForm;
					if (dockForm.AllowMoving == true)
						dockForm.MoveControl(dockForm.Handle);

					this.DockPanel.MakeDocked();
				}
			}

			lastPos = e.Location;
			base.OnMouseMove(e);
		}

		#region Wrappers

		protected override void OnMove(EventArgs e)
		{
			this.CreateBackround();
			base.OnMove(e);
		}

		protected override void OnResize(EventArgs eventargs)
		{
			this.CreateBackround();
			base.OnResize(eventargs);
		}

		protected override void OnBackColorChanged(EventArgs e)
		{
			this.CreateBackround();
			base.OnBackColorChanged(e);
		}

		protected override void OnCreateControl()
		{
			this.CreateBackround();
			base.OnCreateControl();
		}

		#endregion

		#endregion

		#region Private

		private void OnGotFocus(object sender, EventArgs e)
        {
            focused = true;

            // Call Invalidate to start drawing the DockCaption.
            this.Invalidate();

            // Raise our custom focus event.

            if (this.RecieveFocus != null)
                this.RecieveFocus(this, e);
        }

        private void OnLostFocus(object sender, EventArgs e)
        {
            focused = false;

            // Call Invalidate to start drawing the DockCaption.
            this.Invalidate();

            // Raise our custom focus event.

            if (this.ReleaseFocus != null)
                this.ReleaseFocus(this, e);
        }

		/// <summary>
		/// Creates the background and makes it transparent.
		/// </summary>
		private void CreateBackround()
		{
			try
			{
				Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
				Bitmap memoryBitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format24bppRgb);
				Graphics mg = Graphics.FromImage(memoryBitmap);

				mg.FillRectangle(BrushStack.GetBrush(this.Parent.BackColor), rect);

				ImageAttributes attributes = new ImageAttributes();
				float[][] matrixElements = new float[][] {
					        new float[] {1.0F, 0.0F, 0.0F, 0.0F, 0.0F},
							new float[] {0.0F, 1.0F, 0.0F, 0.0F, 0.0F},
							new float[] {0.0F, 0.0F, 1.0F, 0.0F, 0.0F},
							new float[] {0.0F, 0.0F, 0.0F, 0.0F, 0.0F},
							new float[] {0.0F, 0.0F, 0.0F, 0.0F, 1.0F}
				};

				ColorMatrix matrix = new ColorMatrix(matrixElements);
				attributes.SetColorMatrix(matrix);

				Bitmap bitmap = new Bitmap(this.Width, this.Height, PixelFormat.Format24bppRgb);
				Graphics g = Graphics.FromImage(bitmap);

				g.FillRectangle(BrushStack.GetBrush(this.BackColor), rect);
				mg.DrawImage(bitmap, rect, 0, 0, this.Width, this.Height, GraphicsUnit.Pixel, attributes);

				base.BackgroundImage = memoryBitmap;
			}
			catch { }
		}

        #endregion

        #endregion

		/// <summary>
		/// Initializes a new instance of the <see cref="DockCaption"/> class.
		/// </summary>
        public DockCaption()
        {
			renderer = new DockRenderer();

            // Setup basic settings for the DockCaption, to 
            // make it look and act like a caption bar.

            //this.BackColor = Color.Transparent;
            this.BorderStyle = BorderStyle.None;
            this.Dock = DockStyle.Top;

            // Add EventHandlers.

            this.GotFocus += OnGotFocus;
            this.LostFocus += OnLostFocus;
            this.Click += OnGotFocus;

            // Set the size of the DockCaption.
            this.Size = new Size(this.Size.Width, 17);

            // Initialize the Glyphs to enable user interaction.

            optionsGlyph = new OptionsGlyph(this);
            closeGlyph   = new CloseGlyph(this);

            // Add the newly initialized Glyphs to the DockCaption's
            // Controls collection.

            this.Controls.Add(optionsGlyph);
            this.Controls.Add(closeGlyph);

            // Focus the DockCaption to make it draw as focused,
            // and start drawing it. (OnGotFocus calls Invalidate)

            this.Focus();
        }
    }
}
